package com.physics.mps.common.util;

import com.physics.mps.entity.enums.CodeEnum;
import lombok.SneakyThrows;
import okhttp3.*;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author mcsoft
 * @date 2023/8/31 10:21
 */
public class OkHttpUtil {

    private static final long TIMEOUT = 20000L;


    private OkHttpUtil() {
    }

    private static OkHttpClient build(){
        return new OkHttpClient.Builder()
                .callTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                .build();
    }


    /**
     * 调用文件上传接口
     * @see #uploadFile(String, File, String, String)
     * @param url
     * @param file
     * @return
     * @throws IOException
     */
    public static Response uploadFile(String url, File file) throws IOException {
        return uploadFile(url, file, "file") ;
    }

    /**
     * 调用文件上传接口
     * @see #uploadFile(String, File, String, String, Map)
     * @param url
     * @param file
     * @return
     * @throws IOException
     */
    public static Response uploadFile(String url, File file, Map<String, String> params) throws IOException {
        return uploadFile(url, file, "file", params) ;
    }


    /**
     * 调用文件上传接口
     * @see #uploadFile(String, File, String, String)
     * @param url
     * @param file
     * @param fileParamName
     * @return
     * @throws IOException
     */
    public static Response uploadFile(String url, File file, String fileParamName) throws IOException {
        return uploadFile(url, file, fileParamName, "application/octet-stream") ;
    }


    /**
     * 调用文件上传接口
     * @see #uploadFile(String, File, String, String)
     * @param url
     * @param file
     * @param fileParamName
     * @return
     * @throws IOException
     */
    public static Response uploadFile(String url, File file, String fileParamName, Map<String, String> params) throws IOException {
        return uploadFile(url, file, fileParamName, "application/octet-stream", params) ;
    }


    /**
     * 调用文件上传接口
     * @param url               上传文件接口地址
     * @param file              文件
     * @param fileParamName     文件参数名
     * @param contentType       contentType
     * @return
     * @throws IOException
     */
    public static Response uploadFile(String url, File file, String fileParamName, String contentType) throws IOException {
        return uploadFile(url, file, fileParamName, contentType, null);
    }


    /**
     * 上传文件
     *
     * @param url               上传地址
     * @param file              文件
     * @param fileParamName     文件参数名
     * @param contentType       contentType
     * @param params            其他参数
     * @return
     * @throws IOException
     */
    public static Response uploadFile(String url, File file, String fileParamName, String contentType, Map<String, String> params) throws IOException {
        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart(fileParamName, file.getName(), RequestBody.create(MediaType.parse(contentType), file));

        if (!CollectionUtils.isEmpty(params)) {
            params.forEach(builder::addFormDataPart);
        }
        RequestBody requestBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        OkHttpClient client = build() ;
        Response response = client.newCall(request).execute();
        AssertUtil.isFalse(CodeEnum.UPLOAD_EXCEPTION, response.code() == HttpStatus.OK.value());
        return response ;
    }



    /**
     * 下载文件
     * @param url       文件下载 url
     * @param local     本地文件路径
     */
    @SneakyThrows
    public static void download(String url, String local) {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        OkHttpClient client = build() ;
        Path path = Paths.get(local);
        path.toFile().getParentFile().mkdirs();
        try (
                Response response = client.newCall(request).execute();
                OutputStream outputStream = Files.newOutputStream(path)
        ) {
            ResponseBody body = response.body();
            if (body == null) {
                return;
            }
            byte[] bytes = body.bytes();
            outputStream.write(bytes);
            outputStream.flush();
        }
    }





}
